#! /usr/bin/env python
import os, re
from waf_dynamo import dmsdk_add_files, copy_file_task, apidoc_extract_task, platform_supports_feature, platform_graphics_libs_and_symbols
import waflib.Options
import waf_dynamo

def options(opt):
    pass

def build(bld):

    platform_bin_install_path = os.path.join(bld.env["PREFIX"], 'bin', bld.env['PLATFORM'])
    platform_lib_install_path = os.path.join(bld.env["PREFIX"], 'lib', bld.env['PLATFORM'])

    bld.stlib(features = 'cxx embed',
              includes = '. ..',
              source = 'engine_service.cpp',
              target = 'engine_service',
              install_path = platform_lib_install_path,
              embed_source = '../content/profiler.html')

    bld.stlib(features = 'cxx',
              includes = '. ..',
              source = 'engine_service_null.cpp',
              install_path = platform_lib_install_path,
              target = 'engine_service_null')

    source = [
        'engine.cpp',
        'engine_main.cpp',
        'engine_loop.cpp',
        'extension.cpp',
        './script/script_engine.cpp',
        '../proto/engine/engine_ddf.proto']

    if bld.env.PLATFORM in ('js-web', 'wasm-web', 'wasm_pthread-web'):
        source.append('engine_web.cpp')
    elif 'arm64-nx64' in bld.env.PLATFORM:
        source.append('nx64/main_nx64.cpp nx64/engine_nx64.cpp')
    elif bld.env.PLATFORM in ('x86_64-ps4', 'x86_64-ps5'):
        source.append('engine_ps4.cpp')

    bld.stlib(features = 'cxx ddf embed',
                    includes = '../proto . ..',
                    target = 'engine',
                    proto_gen_py = True,
                    protoc_includes = ['../proto', bld.env['PREFIX'] + '/share'],
                    embed_source='../content/materials/debug.spc ../content/builtins/connect/game.project ../content/builtins.arci ../content/builtins.arcd ../content/builtins.dmanifest',
                    source = source + ['physics_debug_render.cpp'],
                    install_path = platform_lib_install_path,
                    use = 'engine_service')

    bld.add_group()

    bld.stlib(features = 'cxx ddf',
                    includes = '../proto . ..',
                    target = 'engine_release',
                    defines = 'DM_RELEASE=1',
                    proto_gen_py = True,
                    protoc_includes = ['../proto', bld.env['PREFIX'] + '/share'],
                    source = source,
                    install_path = platform_lib_install_path,
                    use = 'engine_service_null')

    bld.install_files('${PREFIX}/include/engine', 'engine.h')
    bld.install_files('${PREFIX}/share/proto/engine', '../proto/engine/engine_ddf.proto')

    additional_libs = ['CRASH']

    resource_type_symbols = ['ResourceTypeGameObject', 'ResourceTypeCollection', 'ResourceTypeScript', 'ResourceTypeLua',
                             'ResourceTypeAnim', 'ResourceTypeAnimationSet', 'ResourceTypeGui', 'ResourceTypeGuiScript',
                             'ResourceTypeOgg', 'ResourceTypeOpus', 'ResourceTypeWav',
                             'ResourceTypeFont','ResourceTypeTTF',
                             'ResourceProviderFile', 'ResourceProviderArchive', 'ResourceProviderArchiveMutable', 'ResourceProviderZip']
    component_type_symbols = ['ComponentTypeAnim', 'ComponentTypeScript', 'ComponentTypeGui', 'ComponentTypeMesh', 'ComponentTypeSound']

    exported_symbols = ['DefaultSoundDevice', 'AudioDecoderWav', 'CrashExt', 'LiveUpdateExt',
                        'ScriptBox2DExt', 'ScriptImageExt', 'ScriptModelExt', 'ScriptTypesExt', 'ScriptHttp', 'ScriptFont']

    # Add stb_vorbis and/or tremolo depending on platform
    if bld.env['PLATFORM'] in ('arm64-nx64', 'win32', 'x86_64-win32', 'js-web', 'wasm-web', 'wasm_pthread-web'):
        exported_symbols.append('AudioDecoderStbVorbis')
    elif bld.env['PLATFORM'] in ('x86_64-ps4','x86_64-ps5',):
        pass # dont't add tremolo
    else:
        exported_symbols.append('AudioDecoderTremolo')
        additional_libs.append('TREMOLO')

    if waflib.Options.options.with_opus:
        additional_libs.append('OPUS')
        exported_symbols += ['AudioDecoderOpus']

    graphics_lib, graphics_lib_symbols = platform_graphics_libs_and_symbols(bld.env['PLATFORM'])

    exported_symbols += graphics_lib_symbols

    if 'android' in bld.env['PLATFORM']:
        additional_libs.append('UNWIND')
        additional_libs.append('CPP_RUNTIME')

    if bld.env['PLATFORM'] in ['win32', 'x86_64-win32', 'arm64-nx64', 'arm64-macos', 'x86_64-macos', 'arm64-ios', 'x86_64-ios']:
        sound_lib  = 'SOUND'
    else:
        sound_lib = 'SOUND OPENAL'

    sound_lib = sound_lib.split()

    dynamo_home = os.getenv('DYNAMO_HOME')

    android_jar_paths = [
              '%s/ext/share/java/android-support-multidex.jar' % (dynamo_home),
              '%s/ext/share/java/androidx-multidex.jar' % (dynamo_home),
              '%s/ext/share/java/glfw_android.jar' % (dynamo_home),
              '%s/share/java/gamesys_android.jar' % (dynamo_home),
              '%s/share/java/sound_android.jar' % (dynamo_home)]

    glfw_js = '../../../ext/lib/%s/js/library_glfw.js' % bld.env.PLATFORM

    web_libs = [glfw_js, 'library_sys.js', 'library_script.js', 'library_render.js']
    if not waflib.Options.options.with_openal:
        web_libs += ['library_sound.js']

    main_cpp = 'common/main.cpp'

    bld.add_group()

    profile_null_libs = ['PROFILE_NULL', 'PROFILEREXT_NULL']
    profile_null_symbols = ['ProfilerExt'] # for dmProfiler::SetUpdateFrequency
    profile_symbols = ['ProfilerExt', 'ProfilerBasic']
    profile_lib = ['PROFILE', 'PROFILEREXT']
    if bld.env['PLATFORM'] in ('arm64-nx64', 'x86_64-ps4', 'x86_64-ps5'):
        profile_lib = ['PROFILE', 'PROFILEREXT']

    # remotery isn't supported on all platforms
    if bld.env['PLATFORM'] not in ('js-web', 'wasm-web', 'wasm_pthread-web', 'arm64-nx64', 'x86_64-ps4', 'x86_64-ps5'):
        profile_lib += ['PROFILER_REMOTERY']
        profile_symbols += ['ProfilerRemotery']

    if bld.env['PLATFORM'] in ('js-web', 'wasm-web', 'wasm_pthread-web'):
        profile_lib += ['PROFILER_JS']
        profile_symbols += ['ProfilerJS']
        web_libs += ['library_profile.js']

    if bld.env['PLATFORM'] in ('x86_64-ps4', 'x86_64-ps5', 'x86_64-linux', 'arm64-linux'):
        additional_libs.append('APP')

    platform_lib = [waf_dynamo.platform_get_platform_lib(bld.env.PLATFORM)]

    font_lib = ['FONT']
    if 'font_layout' in waflib.Options.options.enable_features:
        font_lib = ['FONT_LAYOUT']

    additional_libs.extend(font_lib)

    obj = bld(
        features = 'c cxx cprogram apk web extract_symbols',
        use = 'engine_rs PROFILEREXT GAMEOBJECT DDF LIVEUPDATE RESOURCE GAMESYS PHYSICS RECORD RENDER SOCKET SCRIPT LUA EXTENSION HID INPUT PARTICLE RIG DLIB GUI CRASH engine engine_service'.split() + graphics_lib + sound_lib + profile_lib + platform_lib + additional_libs,
        web_libs = web_libs,
        exported_symbols = exported_symbols + profile_symbols + resource_type_symbols + ['ResourceProviderHttp'] + component_type_symbols,
        includes = '../build ../proto . ..',
        #NOTE: _XBOX to get static lib and avoid dllimport/dllexport stuff
        defines = '_XBOX',
        proto_gen_py = True,
        protoc_includes = '../proto',
        target = 'dmengine',
        bundleid = 'com.defold.engine',
        source = main_cpp.split(),
        proguard = ['../content/builtins/manifests/android/dmengine.pro'],
        install_path = platform_bin_install_path,
        jars = android_jar_paths)

    if 'win32' in bld.env.PLATFORM:
        obj.source.append('engine.rc') # Needs to bundle with icons, or IconExe.java won't be able to replace them (it cannot add them)
        obj.env.append_value('LINKFLAGS', ['Psapi.lib'])
        bld.install_files('${PREFIX}/lib/%s' % bld.env['PLATFORM'], 'defold.ico')
        bld.install_files('${PREFIX}/lib/%s' % bld.env['PLATFORM'], 'engine.rc')

    if 'android' in bld.env['PLATFORM']:
        bld.install_files('${PREFIX}/share/java', 'dmengine.android/classes.dex')

    bld.add_group()

    obj = bld(
        features = 'c cxx cprogram apk web extract_symbols',
        use = 'GAMEOBJECT DDF LIVEUPDATE RESOURCE GAMESYS PHYSICS RECORD RENDER SOCKET SCRIPT LUA EXTENSION HID INPUT PARTICLE RIG DLIB GUI CRASH engine_release engine_service_null'.split() + graphics_lib + sound_lib + platform_lib + additional_libs + profile_null_libs,
        web_libs = web_libs,
        exported_symbols = exported_symbols + profile_null_symbols + resource_type_symbols + component_type_symbols,
        includes = '../build ../proto . ..',
        #NOTE: _XBOX to get static lib and avoid dllimport/dllexport stuff
        defines = '_XBOX DM_RELEASE=1',
        proto_gen_py = True,
        protoc_includes = '../proto',
        target = 'dmengine_release',
        source = main_cpp.split(),
        install_path = platform_bin_install_path,
        jars   = android_jar_paths)

    if 'win32' in bld.env.PLATFORM:
        obj.source.append('engine.rc')
        obj.env.append_value('LINKFLAGS', ['/SUBSYSTEM:WINDOWS', '/ENTRY:mainCRTStartup', 'Psapi.lib'])

    additional_libs = []
    if bld.env['PLATFORM'] in ('armv7-android', 'arm64-android', 'x86_64-macos'):
        additional_libs += ['UNWIND']

    if bld.env['PLATFORM'] in ('x86_64-ps4', 'x86_64-ps5'):
        additional_libs.append('APP')

    additional_libs.extend(font_lib)

    exported_symbols = ['ProfilerExt', 'LiveUpdateExt', 'ScriptTypesExt', 'GraphicsAdapterNull',
                        'ScriptFont','ResourceTypeFont','ResourceTypeTTF']

    graphics_lib = 'GRAPHICS_NULL'
    if bld.env['PLATFORM'] in ('arm64-android','armv7-android', 'arm64-ios', 'x86_64-ios'):
        graphics_lib = 'GRAPHICS_NULL DMGLFW' # g_AndroidApp is currently in glfw. UIApplicationMain is currently in glfw

    bld.add_group()

    obj = bld(
        features = 'c cxx cprogram apk web extract_symbols',
        use = 'RECORD_NULL GAMEOBJECT DDF LIVEUPDATE GAMESYS RESOURCE PHYSICS RENDER SOCKET SCRIPT LUA EXTENSION HID_NULL INPUT PARTICLE PLATFORM_NULL RIG GUI CRASH DLIB SOUND_NULL engine engine_service'.split() + graphics_lib.split() + profile_lib + additional_libs,
        exported_symbols = ['LiveUpdateExt', 'ScriptTypesExt', 'GraphicsAdapterNull'] + profile_symbols + resource_type_symbols + component_type_symbols,
        web_libs = web_libs,
        includes = '../build ../proto . ..',
        proto_gen_py = True,
        protoc_includes = '../proto',
        target = 'dmengine_headless',
        install_path = platform_bin_install_path,
        source = main_cpp.split())

    if 'win32' in bld.env.PLATFORM:
        obj.source.append('engine.rc')
        obj.env.append_value('LINKFLAGS', ['Psapi.lib'])

    if 'arm64-nx64' in bld.env['PLATFORM']:
        bld.install_files('${PREFIX}/bin/${PLATFORM}', 'dmengine.nso')
        bld.install_files('${PREFIX}/bin/${PLATFORM}', 'dmengine_release.nso')
        bld.install_files('${PREFIX}/bin/${PLATFORM}', 'dmengine_headless.nso')

    if not waflib.Options.options.skip_build_tests:
        bld.recurse('test')

    dmsdk_add_files(bld, '${PREFIX}/sdk/include/dmsdk', 'dmsdk')

    apidoc_extract_task(bld, ['../proto/engine/engine_ddf.proto', 'engine_doc.h'])

def configure(conf):
    pass
